#!/usr/bin/python

from .. import conv, function, metric, silk

class Error(silk.Error):
  """Used to signal errors during trace formatting."""
  pass

def format(trace, indent=0):
  string = ''

  lines = []
  for obj in trace:
    t = type(obj['obj'])
    if issubclass(t, function.Function):
      lines.append(format_func(obj))
    elif issubclass(t, function.Param):
      lines.append(format_param(obj))
    elif issubclass(t, metric.MetricAggregation):
      lines.append(format_aggr(obj))
    else:
      raise Error('Unknown object type "%s" encountered in trace' % t)

  return indent_lines(lines, indent)

def indent_lines(lines, indent):
  string = ',\n'.join(lines) + '\n'
  lines = string.split('\n')
  lines = [' ' * indent + line for line in lines]
  lines[-1] = lines[-1][indent:]
  return '\n'.join(lines)

def format_func(func):
  if type(func['value']) is list:
    eval_str = '[' + ', '.join(["'%s'" % x['value'] for x in func['value']]) + ']'
  else:
    eval_str = func['value']

  return ('<span class="function_name">%s</span>(\n%s) = <span '
          'class="function_value">%s</span> <span class="metric_options">[W:%s '
          'O:%s D:%s]</span>') % (
    func['obj'].identifier, format(func['params'], 2), eval_str,
    func.get('weight', '-'), func.get('optional', '-'),
    func.get('default', '-')
  )

def format_aggr(aggr):
  return ('<span class="aggr_name">%s</span>(\n%s) = <span '
          'class="aggr_value">%s</span> <span class="aggr_options">[W:%s O:%s '
          'D:%s]</span>') % (
    aggr['obj'].aggr_type, format(aggr['metrics'], 2), aggr['value'],
    aggr.get('weight', '-'), aggr.get('optional', '-'),
    aggr.get('default', '-')
  )

def format_param(param):
  if 'path' in param:
    eval_str = '[' + ', '.join(["'%s'" % x['value'] for x in param['value']]) + ']'
    value = ('<span class="function_name">path</span>(<span '
             'class="param_value">"%s"</span>) = %s') % (str(param['path'].path), eval_str)
  else:
    value = '<span class="param_value">"%s"</span>' % conv.string(param['value'][0])

  return '<span class="param_name">%s</span> = %s' % (param['name'], value)
